<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Convid-vis Demo</title>
</head>
<body>
  <script src="https://lib.baomitu.com/topojson/3.0.2/topojson.min.js"></script>
  <canvas width="1024" height="512"></canvas>
  <script>
    /* globals topojson */
    const width = 1024;
    const height = 512;
    function projection([longitude, latitude]) {
      const x = width * (180 + longitude) / 360;
      const y = height * (1.0 - (90 + latitude) / 180); // Canvas坐标系y轴朝下
      return [x, y];
    }

    function drawPoints(ctx, points) {
      ctx.beginPath();
      ctx.moveTo(...points[0]);
      for(let i = 1; i < points.length; i++) {
        ctx.lineTo(...points[i]);
      }
      ctx.fill();
    }

    function mapDataToCountries(geoData, convidData) {
      const convidDataMap = {};
      convidData.dailyReports.forEach((d) => {
        const date = d.updatedDate;
        const countries = d.countries;
        countries.forEach((country) => {
          const name = country.country;
          convidDataMap[name] = convidDataMap[name] || {};
          convidDataMap[name][date] = country;
        });
      });
      geoData.features.forEach((d) => {
        const name = d.properties.name;
        d.properties.convid = convidDataMap[name];
      });
    }

    function mapColor(confirmed) {
      if(confirmed < 10) {
        return 'rgb(250, 247, 171)';
      }
      if(confirmed < 100) {
        return 'rgb(255, 186, 66)';
      }
      if(confirmed < 500) {
        return 'rgb(234, 110, 41)';
      }
      if(confirmed < 1000) {
        return 'rgb(224, 81, 57)';
      }
      if(confirmed < 10000) {
        return 'rgb(192, 50, 39)';
      }
      return 'rgb(151, 32, 19)';
    }

    function drawMap(ctx, countries, date) {
      ctx.fillStyle = '#3ac';
      countries.features.forEach(({geometry, properties}) => {
        const convid = properties.convid ? properties.convid[date] : null;
        if(convid) {
          const confirmed = convid.confirmed;
          if(confirmed) {
            ctx.fillStyle = mapColor(confirmed);
          }
        }
        if(geometry.type === 'MultiPolygon') {
          const coordinates = geometry.coordinates;
          if(coordinates) {
            coordinates.forEach((contours) => {
              contours.forEach((path) => {
                const points = path.map(projection);
                drawPoints(ctx, points);
              });
            });
          }
        } else if(geometry.type === 'Polygon') {
          const contours = geometry.coordinates;
          contours.forEach((path) => {
            const points = path.map(projection);
            drawPoints(ctx, points);
          });
        }
      });
    }

    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d');

    (async function () {
      const worldData = await (await fetch('./assets/data/world-topojson.json')).json();
      const countries = topojson.feature(worldData, worldData.objects.countries);

      const convidData = await (await fetch('./assets/data/convid-data.json')).json();
      mapDataToCountries(countries, convidData);
      drawMap(ctx, countries, '2020-01-22');
    }());
  </script>
</body>
</html>